package com.tarzan.gateway.service;

import com.tarzan.gateway.repository.MyRouteDefinitionRepository;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @Package com.tarzan.gateway.service
 * @Title GateWayDynamicRouteService
 * @Description TODO
 * @Author liujinshan
 * @CreateTime 2021/11/12 14:48
 */
@Service
public class GateWayDynamicRouteService implements ApplicationEventPublisherAware {

    @Resource
    private MyRouteDefinitionRepository myRouteDefinitionRepository;

    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * Set the ApplicationEventPublisher that this object runs in.
     * <p>Invoked after population of normal bean properties but before an init
     * callback like InitializingBean's afterPropertiesSet or a custom init-method.
     * Invoked before ApplicationContextAware's setApplicationContext.
     *
     * @param applicationEventPublisher event publisher to be used by this object
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }


    /**
     * @title add
     * @description TODO
     * @param routeDefinition
     * @return int 
     * @author liujinshan
     * @data 2021/11/12 15:02
     */
    public int add(RouteDefinition routeDefinition){
        myRouteDefinitionRepository.save(Mono.just(routeDefinition));
        applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        return 1;
    }

    /**
     * @title update
     * @description TODO
     * @param routeDefinition
     * @return int 
     * @author liujinshan
     * @data 2021/11/12 15:02
     */
    public int update(RouteDefinition routeDefinition){
        myRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId()));
        myRouteDefinitionRepository.save(Mono.just(routeDefinition));
        applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        return 1;
    }

    /**
     * @title delete
     * @description TODO
     * @param id
     * @return reactor.core.publisher.Mono<org.springframework.http.ResponseEntity<java.lang.Object>> 
     * @author liujinshan
     * @data 2021/11/12 15:02
     */
    public Mono<ResponseEntity<Object>> delete(String id){
        return myRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(()->
                Mono.just(ResponseEntity.ok().build())))
                .onErrorResume(t -> t instanceof NotFoundException,t->
                        Mono.just(ResponseEntity.notFound().build()));
    }


    public void refresh(){
        applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
    }
}
